using System;
using System.Collections.Generic;
using System.Text;

namespace NetSpider.Retrieval
{
    public class ContentNode : IContentNode
    {
        public static readonly IContentNode Null = new NullContentNode();

        //private IContent _content;
        private string _parentUri;
        private bool _isRootNode;
        private List<IContentNode> _branchNodes;
        private IContentTree _parentTree;
        private IFetchResult _fetchResult;

        public static IContentNode Create(IContentTree parentTree, IFetchResult fetchResult)
        {
            return new ContentNode(parentTree, fetchResult, string.Empty, true);
        }

        private ContentNode(IContentTree parentTree, IFetchResult fetchResult, string parentUri, bool isRootNode)
        {
            _parentTree = parentTree;
            _fetchResult = fetchResult;
            _parentUri = parentUri;
            _isRootNode = isRootNode;
            _branchNodes = new List<IContentNode>();
        }

        public IContentNode[] GetChildren()
        {
            return _branchNodes.ToArray();
        }

        public IContentNode CreateChild(IFetchResult fetchResult)
        {
            IContentNode branchNode;
            IContentNode found = _parentTree.FindNode(fetchResult.GetRequest().RequestedUri.ToString());
            if (found == Null)
            {
                branchNode = new ContentNode(_parentTree, fetchResult, _fetchResult.GetRequest().RequestedUri.ToString(), false);
                _branchNodes.Add(branchNode);
            }
            else
            {
                branchNode = new ReferenctContentNode(found);
            }
            return branchNode;
        }

        public IContent GetContent()
        {
            return _fetchResult.GetContent();
        }

        public string ParentUri
        {
            get { return _parentUri; }
        }

        public bool IsRootNode
        {
            get { return _isRootNode; }
        }

        public bool IsReferenceNode
        {
            get { return false; }
        }

        private class NullContentNode : IContentNode
        {
            public IContentNode[] GetChildren()
            {
                return new IContentNode[0];
            }

            public IContentNode CreateChild(IFetchResult fetchResult)
            {
                return this;
            }

            public IContent GetContent()
            {
                return NullContent.Value;
            }

            public string ParentUri
            {
                get { return string.Empty; }
            }

            public bool IsRootNode
            {
                get { return false; }
            }

            public bool IsReferenceNode
            {
                get { return false; }
            }
        }

        private class ReferenctContentNode : IContentNode
        {
            private readonly IContentNode _original;

            public ReferenctContentNode(IContentNode original)
            {
                _original = original;
            }

            public IContentNode[] GetChildren()
            {
                return _original.GetChildren();
            }

            public IContentNode CreateChild(IFetchResult fetchResult)
            {
                return _original.CreateChild(fetchResult);
            }

            public IContent GetContent()
            {
                return _original.GetContent();
            }

            public string ParentUri
            {
                get { return _original.ParentUri; }
            }

            public bool IsRootNode
            {
                get { return _original.IsRootNode; }
            }

            public bool IsReferenceNode
            {
                get { return true; }
            }
        }
    }
}
